// DMPluginWrapper.h

#pragma once

#include "dmalgointerfaces.h"


using namespace System;

#include "DMEnumerationWrappers.h"
#include "DMMiningParameter.h"
#include "DMCustomFunctions.h"
#include "DMProgrammingAttributes.h"


namespace Microsoft
{
namespace SqlServer
{
namespace DataMining
{
namespace PluginAlgorithms
{
    ref class AttributeSet;    
	ref class AlgorithmBase;
	ref class ModelServices;
	ref class CustomFunctionInfo;
	


    public   ref class AlgorithmMetadataBase abstract: 
                            public ICLR_DMAlgorithmFactory,
                            public ICLR_DMAlgorithmMetadata,
							public ICLR_DMCustomFunctionInfo,
							public ICLR_SupportErrorInfo
	{
    private:
        // Constants
        ContextServices ^			m_context;
	public:
	internal:
		static CustomFunctionInfo^  ValidateFunction(DM_SUPPORTED_FUNCTION	in_FunctionOrdinal, array<CustomFunctionInfo^>^ in_rgSuppFunctions);
		static VARTYPE				VARTYPEFromSystemType(Type^ type);


	protected:
            // Constructor
        AlgorithmMetadataBase();


        // Destructor
        ~AlgorithmMetadataBase();
	public:




        // property accessible from inside the derived classes
		property ContextServices ^    Context
		{
			ContextServices ^    get()
			{
				return m_context;
		    }
		}
	public:
        // Interface ICLR_DMALgorithmMetadata
		virtual HRESULT ExportedCreateAlgorithm(
			IDMModelServices*   in_pModel,
			IDMAlgorithm**      out_ppAlgo)sealed;

        // Interface ICLR_DMALgorithmMetadata
		virtual HRESULT ExportedGetServiceType(
			IDMContextServices* in_pContext ,
			ULONG*              out_pServiceTypeID)sealed;

		
		virtual HRESULT ExportedGetServiceName(
			IDMContextServices* in_pContext ,
			DMString*           io_pstrServiceName)sealed;

        
		virtual HRESULT ExportedGetDisplayName(
			IDMContextServices* in_pContext ,
			DMString*           io_pstrDescription)sealed;

        
		virtual HRESULT ExportedGetServiceGuid(
			IDMContextServices* in_pContext ,
			GUID*				out_pguidServiceGUID)sealed;

        
		virtual HRESULT ExportedGetDescription(
			IDMContextServices* in_pContext ,
			DMString*           io_pstrDescription)sealed;

        
		virtual HRESULT ExportedGetPredictionLimit(
			IDMContextServices* in_pContext ,
			LONG*               out_pPredictionLimit)sealed;

        
		virtual HRESULT ExportedGetSupDistributionFlags(
			IDMContextServices* in_pContext ,
			ULONG**             out_prgFlags,
			ULONG*              out_pcFlags)sealed;

        
		virtual HRESULT ExportedGetSupInputContentTypes(
			IDMContextServices* in_pContext ,
			ULONG**             out_prgTypes,
			ULONG*              out_pcTypes)sealed;


        
		virtual HRESULT ExportedGetSupPredictContentTypes(
			IDMContextServices* in_pContext ,
			ULONG**             out_prgTypes,
			ULONG*              out_pcTypes)sealed;


        
		virtual HRESULT ExportedGetSupModelingFlags(
			IDMContextServices* in_pContext ,
			DM_MODELING_FLAG**  out_prgFlags,
			ULONG*              out_pcFlags)sealed;

        
		virtual HRESULT ExportedGetModelingFlagName(
			IDMContextServices* in_pContext ,
            DM_MODELING_FLAG	in_Flag,
			DMString*           io_pstrFlagName)sealed;


	    
        virtual HRESULT ExportedGetTrainingComplexity(	
                        IDMContextServices*	in_pContext,
                        LONG*					out_pTrainingComplexity	)sealed;

	    
        virtual HRESULT ExportedGetPredictionComplexity			(	
                        IDMContextServices*	in_pContext,
                        LONG*					out_pPredictionComplexity	)sealed;

	    
        virtual HRESULT ExportedGetExpectedQuality				(	
                        IDMContextServices*	in_pContext,
                        LONG*					out_pExpectedQuality		)sealed;

	    
        virtual HRESULT ExportedGetScaling						(	
                        IDMContextServices*	in_pContext,
                        LONG*					out_pScaling				)sealed;

	    
        virtual HRESULT ExportedGetAllowIncrementalInsert		(	
                        IDMContextServices*	in_pContext,
                        BOOL*					out_pfIncrementalInsert		)sealed;

	    
        virtual HRESULT ExportedGetAllowDuplicateKey			(	
                        IDMContextServices*	in_pContext,
                        BOOL*					out_pfDuplicateKey			)sealed;

	    
        virtual HRESULT ExportedGetControl						(	
                        IDMContextServices*	in_pContext,
                        LONG*					out_pControl				)sealed;

	    
        virtual HRESULT ExportedGetViewerType					(	
                        IDMContextServices*	in_pContext,
                        DMString *			io_pstrViewerType			)sealed;

	    
        virtual HRESULT ExportedGetSupportsDMDimensions			(	
                        IDMContextServices*	in_pContext,
                        BOOL*					out_pfSupportsDMDimensions	)sealed;

	    
        virtual HRESULT ExportedGetSupportsDrillthrough			(	
                        IDMContextServices*	in_pContext,
                        BOOL*					out_pfSupportsDrillthrough,
                        BOOL*					out_pfMustIncludeChildren	)sealed;

	    
        virtual HRESULT ExportedGetSupportedFunctions			(	
                        IDMContextServices*	in_pContext,
                        DM_SUPPORTED_FUNCTION **	out_prgFuncs,
                        ULONG *				out_cFuncs					)sealed;

	//-------------------------------------------------------------------------
	// Service parameters access

	    
        virtual HRESULT ExportedGetNumParameters				(	
                        IDMContextServices*	in_pContext,
                        ULONG*				out_pcParameters			)sealed;

	    
        virtual HRESULT ExportedGetParameterName				(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        DMString *			io_pstrParameterName		)sealed;

	    
        virtual HRESULT ExportedGetParameterType				(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        DMString *			io_pstrParameterType		)sealed;

	    
        virtual HRESULT ExportedGetParameterIsRequired			(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        BOOL*					out_pfIsRequired			)sealed;

	    
        virtual HRESULT ExportedGetParameterIsExposed			(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        BOOL*					out_pfIsExposed				)sealed;

	    
        virtual HRESULT ExportedGetParameterFlags				(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        ULONG*				out_pulParameterFlags		)sealed;

	    
        virtual HRESULT ExportedGetParameterDescription			(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        ULONG					in_LocaleID,
                        DMString *			io_pstrDescription			)sealed;

	    
        virtual HRESULT ExportedGetParameterDefaultValue		(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        DMString *			io_pstrDefaultValue			)sealed;

	    
        virtual HRESULT ExportedGetParameterValueEnumeration	(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        DMString *			io_pstrValueEnumeration		)sealed;

	    
        virtual HRESULT ExportedParseParameterValue				(	
                        IDMContextServices*	in_pContext,
                        ULONG					in_iParameter,
                        DMString *			in_pstrParameterStrValue,
                        DMVariantPtr			io_pParameterMappedValue	)sealed;

	//-------------------------------------------------------------------------
	// Algorithm Limitations and requirements

	    
        virtual HRESULT ExportedGetMarginalRequirements			(	
                        IDMContextServices*	in_pContext,
                        DMMarginalRequirements*	out_pReq)sealed;

	    
        virtual HRESULT ExportedGetCaseIDModelled				(	
                        IDMContextServices*	in_pContext,					
                        BOOL*					out_pfIsModelled)sealed;

	//-------------------------------------------------------------------------
	// Validation: Each algorithm has to validate the model using IDMAttributeSet.
	// Note that IDMAttributeSet has not been fully populated in that we have not
	// actually read the training cases yet. For instance, # of states, # of
	// attributes in a nested table won't be available at this time. However,
	// it's been populated enough to validate the structure of the model.
	//  The only valid methods to call are:
	//		GetAttributeFlags
	//		GetAttributeCount		(returns the number of attributes you can query on, not the actual attributes that will be in the dataset)
	//		IsFunctionallyDependant
	//		IsCaseAttribute
	//
	//-------------------------------------------------------------------------
	    
        virtual HRESULT ExportedValidateAttributeSet			(	
                        IDMContextServices*	in_pContext,
                        IDMAttributeSet*		in_pAttributeSet)sealed;


	//-------------------------------------------------------------------------
	// Metadata should return TRUE only if the algorithm supports one of the following operations:
	//	- initialization from PMML
	//	- generating PMML 
	//-------------------------------------------------------------------------
        virtual HRESULT ExportedGetSupportsPMML			(	
                        IDMContextServices*	in_pContext,
                        BOOL*		out_pfSupportsPMML)sealed;

    


	//-------------------------------------------------------------------------
	// FunctionInfo interface
	//-------------------------------------------------------------------------
		virtual HRESULT ExportedGetName(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            DMString *			io_pstrName)sealed;


		
		virtual HRESULT ExportedGetSignature(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            DMString *			io_pstrSignature)sealed;


		
		virtual HRESULT ExportedGetReturnsTable(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            BOOL*			out_pfReturnsTable)sealed;

		
		virtual HRESULT ExportedGetDescription(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            DMString *			io_pstrDescription)sealed;


		
		virtual HRESULT ExportedGetHelpFile(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            DMString *			io_pstrHelpFile)sealed;

    
		
		virtual HRESULT ExportedGetHelpContext(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            LONG *			io_pHelpContext)sealed;

		
		virtual HRESULT ExportedGetNumParameters(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            ULONG *			out_pcParameters)sealed;

		
		virtual HRESULT ExportedGetNumFlags(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
            ULONG *			out_pcFlags)sealed;


		
		virtual HRESULT ExportedGetParameterType(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
			ULONG				in_iParameter,
            DM_FUNC_PARAM_TYPE*	out_pType)sealed;


		
		virtual HRESULT ExportedGetParameterDataType(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
			ULONG				in_iParameter,
            VARTYPE*	out_pDataType)sealed;

		
		virtual HRESULT ExportedGetParameterIsRequired(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
			ULONG				in_iParameter,
            BOOL*	out_pfIsRequired)sealed;


		
		virtual HRESULT ExportedGetFlagName(
			IDMContextServices* in_pContext,
			DM_SUPPORTED_FUNCTION in_Function,
			ULONG			in_iFlag,
            DMString *		io_pstrName)sealed;

		//ISupportErrorInfo interface
		virtual HRESULT ExportedInterfaceSupportsErrorInfo(
				REFIID			riid)sealed;


        private:
            //
            //    Pinned arrays of enumerated values. 
            //    These are members to keep them in scope after returning from 
            //    GetSup functions
            //
            ULONG*                          m_rgSupInputContentTypes;
            ULONG                           m_cSupInputContentTypes;

            ULONG*                          m_rgSupPredictContentTypes;
            ULONG                           m_cSupPredictContentTypes;

            DM_MODELING_FLAG*               m_rgSupModelingFlags;
            ULONG                           m_cSupModelingFlags;

            DM_SUPPORTED_FUNCTION*          m_rgSupFunctions;
            ULONG                           m_cSupFunctions;

            /*
                Managed cached members
            */
            MiningParameterCollection ^		m_params;

			array<CustomFunctionInfo^>^		m_rgCustomFunctions;
			void							BuildCustomFunctionInfo();
			CustomFunctionInfo^				PopulateCustomFunctionInfo( MethodInfo^ mi, MiningFunctionAttribute^ attrInfo );

			String^							GetServiceGuid();

        public:
          /*
                These functions MUST be overridden
            */
            virtual PlugInServiceType           GetServiceType()    =   0;
            
            virtual String ^					GetServiceName()    =   0;
            
            virtual String ^					GetDisplayName()    =   0;
            
            virtual String ^					GetServiceDescription()    =   0;

			virtual System::Int32               GetPredictionLimit(){ return 0;}

            virtual array<MiningColumnContent>^ GetSupInputContentTypes() = 0;
            
            virtual array<MiningColumnContent>^ GetSupPredictContentTypes() = 0;

			virtual array<MiningModelingFlag>^  GetSupModelingFlags(){return nullptr;};

			virtual String ^                GetModelingFlagName(MiningModelingFlag  flag) {return nullptr;};

            virtual MiningTrainingComplexity    GetTrainingComplexity() = 0; 
            
            virtual MiningPredictionComplexity  GetPredictionComplexity() = 0;

            virtual MiningExpectedQuality       GetExpectedQuality() = 0;

            virtual MiningScaling               GetScaling() = 0;

			virtual bool                        GetAllowIncrementalInsert() {return false;};
            
			virtual bool                        GetAllowDuplicateKey() {return false;};

			virtual System::Int32               GetControl() {return 0;};

            virtual String ^                GetViewerType() = 0;

            virtual bool                        GetSupportsDMDimensions() = 0;

            virtual bool                        GetSupportsDrillThrough() = 0;

            virtual bool                        GetDrillThroughMustIncludeChildren() = 0;

            virtual array<SupportedFunction>^   GetSupportedStandardFunctions() = 0;

            virtual MiningParameterCollection ^ GetParametersCollection() = 0;

            virtual Object ^					ParseParameterValue( int parameterIndex, String ^ parameterValue) = 0;

            virtual MarginalRequirements        GetMarginalRequirements() = 0;

            virtual bool                        GetCaseIdModeled() = 0;

            virtual void                        ValidateAttributeSet(AttributeSet ^ attributeSet) = 0;

			virtual AlgorithmBase ^				CreateAlgorithm(ModelServices ^	model) = 0;
	
			[System::Diagnostics::CodeAnalysis::SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased")]
			virtual bool						SupportsPMML()
			{
				return false;
			}

        private:
            void EnsureParameters()
            {
                if( m_params == nullptr )
                {
                    m_params = GetParametersCollection();
                }
            }


	};
}
}
}
}
